/*
 * Copyright 2010-2015 icl-network.com. All rights reserved.
 * Support: http://www.icl-network.com
 */
package com.dream.technology.utils.parse;


import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * map 转对象
 */
public final class MapUtils {
	
	private MapUtils() {
	}

	private static Pattern linePattern = Pattern.compile("_(\\w)");
	/**
	 * 把map的值赋值到clazz 
	 * @param clazz 目标clazz 
	 * @param map 带值的map
	 * @return 赋值后的目标实体对象 
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
    public static <T> T mapToBean(Class<T> clazz,Map map) throws Exception{
        //实例化类  
        T entity = (T)clazz.newInstance();  
        Set<String> keys = map.keySet();
		// 这里一定要注册默认值，使用null也可以
		BigDecimalConverter bd = new BigDecimalConverter(BigDecimal.ZERO);
		ConvertUtils.register(bd, BigDecimal.class);
//		ConvertUtils.register(new DateConverter(null), java.util.Date.class);
		BeanUtils.populate(entity,map);
//        List<Field> allFieldsList = FieldUtils.getAllFieldsList(clazz);
//        HashMap<String, Field> stringFieldHashMap = new HashMap<>();
//        allFieldsList.forEach(field -> {
//            stringFieldHashMap.put(field.getName(),field);
//        });
//        //变量map 赋值
//        for(String fieldName:keys){
//            //设置赋值
//            try {
//                //参数的类型  clazz.getField(fieldName)
//                Class<?> paramClass = stringFieldHashMap.get(fieldName).getType();
//                //拼装set方法名称
//                String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
//                //根据名称获取方法
//                Method method = clazz.getMethod(methodName, paramClass);
//                //调用invoke执行赋值
//                method.invoke(entity, map.get(fieldName));
//            } catch (Exception e) {
//                //Console.error("转换对象错误：",e);
//            }
//        }
        return entity;


    }


	/**
	 * <p class="detail">
	 * 功能： Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean
	 * 	固定hibernateBean类型转换:  user_name 转 userName ,注意严格验证参数
	 *
	 * </p>
	 * @author wuxw
	 * @param map
	 * @param obj
	 * @throws
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <T>T transMapHiberanteBean(Class<T> clazz, Map map) throws IllegalAccessException, InstantiationException {


		Map mapData = unversonKey(map);

		T entity =clazz.newInstance();
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

			for (PropertyDescriptor property : propertyDescriptors) {
				String key = property.getName();
				//将key中大写字符转为_大写
//				key = underscoreName(key);
				key = lineToHump(key,linePattern);
				if (mapData.containsKey(key)) {
					Object value = mapData.get(key);
					// 得到property对应的setter方法
					Method setter = property.getWriteMethod();
					setter.invoke(entity, value);
				}

			}

		} catch (Exception e) {
			//Console.error("transMapBean Error " + e);
		}

		return entity;

	}

	/**
	 * 把map key 大写的下划线转
	 * @param map
	 * @return
	 */
	public static Map unversonKey(Map<String,Object> map){
		HashMap<String, Object> stringObjectHashMap = new HashMap<>();
		map.forEach((k,v)->{
			stringObjectHashMap.put(lineToHump(k,linePattern),v);
		});
		return  stringObjectHashMap;
	}

	/**
	 * <p class="detail">
	 * 功能：将大写转为下划线,且小写 如: userName > user_name
	 * </p>
	 * @author wuxw
	 * @param name
	 * @return
	 * @throws
	 */
	static String underscoreName(String name)
	{
		StringBuilder result = new StringBuilder();
		if ((name != null) && (name.length() > 0)) {
			result.append(name.substring(0, 1).toLowerCase());
			for (int i = 1; i < name.length(); ++i) {
				String s = name.substring(i, i + 1);
				if (s.equals(s.toUpperCase())) {
					result.append("_");
					result.append(s.toLowerCase());
				}
				else {
					result.append(s);
				}
			}
		}
		return result.toString();
	}


	/**下划线转驼峰*/
	public static String lineToHump(String str , Pattern pattern){
//        str = str.toLowerCase();
		Matcher matcher = pattern.matcher(str);
		StringBuffer sb = new StringBuffer();
		while(matcher.find()){
			matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
		}
		matcher.appendTail(sb);
		return sb.toString();
	}
}